<?php

namespace fast\console\command;

use fast\Cache;
use fast\Config;
use fast\console\Command;
use fast\console\Input;
use fast\console\Output;
use voku\helper\HtmlDomParser;

class Build extends Command
{
    protected function configure()
    {
        $this->setName('build')->setDescription('打包静态文件');
    }

    protected function execute(Input $input, Output $output)
    {
        $view_path = THEMES_PATH . "/view";
        if (!is_dir($view_path)) {
            $output->writeln("<error>build error view 目录不存在</error>");
            return;
        }

        $this->callbackDir($output, $view_path);


        $output->writeln(THEMES_PATH);
    }

    private function callbackDir(Output $output, $path)
    {
        if (!$handle = opendir($path)) {
            $output->writeln("<error>build error view 目录打开失败</error>");
            return;
        }

        while (($file = readdir($handle)) !== false) {
            if ($file === '.' || $file === '..') {
                continue;
            }

            $sub_dir = realpath("{$path}/{$file}");
            if (is_dir($sub_dir)) {
                $this->callbackDir($output, $sub_dir);
                continue;
            }

            if (pathinfo($file, PATHINFO_EXTENSION) !== 'html') {
                continue;
            }

            $file_path = str_replace(THEMES_PATH . "/view/", '', $sub_dir);
            $content   = file_get_contents($sub_dir);
            $this->build($file_path, $content);

            $output->writeln("<info>{$file_path} success</info>");

        }

    }

    private function build($path, $content)
    {

        $build_view_dir = THEMES_PATH . "/view_build/";
        if (!is_dir($build_view_dir) && !mkdir($build_view_dir, 0777, true) && !is_dir($build_view_dir)) {
            throw new \RuntimeException(sprintf('Directory "%s" was not created', $build_view_dir));
        }
        $build_assets_dir    = THEMES_PATH . "/assets_build";
        $build_assets_js_dir = $build_assets_dir . "/js/";
        if (!is_dir($build_assets_js_dir) && !mkdir($build_assets_js_dir, 0777, true) && !is_dir($build_assets_js_dir)) {
            throw new \RuntimeException(sprintf('Directory "%s" was not created', $build_assets_js_dir));
        }
        $build_assets_css_dir = $build_assets_dir . "/css/";
        if (!is_dir($build_assets_css_dir) && !mkdir($build_assets_css_dir, 0777, true) && !is_dir($build_assets_css_dir)) {
            throw new \RuntimeException(sprintf('Directory "%s" was not created', $build_assets_css_dir));
        }

        $build_view_name       = $build_view_dir . $path;
        $build_assets_js_name  = $build_assets_js_dir . md5($path) . ".js";
        $build_assets_css_name = $build_assets_css_dir . md5($path) . ".css";

        $content = $this->buildCss($build_assets_css_name, $content);
        $content = $this->buildJs($build_assets_js_name, $content);

        $sub_build_view_dir = dirname($build_view_name);
        if (!is_dir($sub_build_view_dir) && !mkdir($sub_build_view_dir, 0777, true) && !is_dir($sub_build_view_dir)) {
            throw new \RuntimeException(sprintf('Directory "%s" was not created', $sub_build_view_dir));
        }

        file_put_contents($build_view_name, $content);
    }

    private function buildJs($build_js_name, $html)
    {
        $build_js_is_exist = file_exists($build_js_name);
        $htmlDomParser     = HtmlDomParser::str_get_html($html);
        $element           = $htmlDomParser->getElementsByTagName('script');
        $build_js          = '';
        $count             = 0;
        foreach ($element as $value) {
            $ignore_assets = Config::get('build.ignore_assets');
            $href          = $value->getAttribute('src');
            if (mb_strpos($href, '.js')) {
                if (!$build_js_is_exist) {
                    switch (true) {
                        case strpos($href, "//") !== false:
                            $href_path = $href;
                            break;
                        case strpos($href, '{{$this->options->themeUrl(\'') !== false:
                            $href_path = THEMES_PATH . '/' . trim(str_replace(['{{$this->options->themeUrl(\'', '\')}}'], ['', ''], $href));
                            $href_path = explode('.js', $href_path)[0] . ".js";
                            break;
                        case strpos($href, '{{$this->options->themeUrl("') !== false:
                            $href_path = THEMES_PATH . '/' . trim(str_replace(['{{$this->options->themeUrl("', '")}}'], ['', ''], $href));
                            $href_path = explode('.js', $href_path)[0] . ".js";
                            break;
                        default:
                            throw new \RuntimeException("build js error {$href}");
                    }

                    $cacheKey = "build:js:" . md5($href);
                    $temp_js  = Cache::get($cacheKey);
                    if (!$temp_js && !in_array($href_path, $ignore_assets)) {
                        $temp_js = file_get_contents($href_path);
                        Cache::set($cacheKey, $temp_js);
                    }
                    $build_js .= "\r\n// {$href_path} \r\n";
                    $build_js .= $temp_js;
                    $build_js .= "\r\n";
                }

                if (!in_array($href_path, $ignore_assets)) {
                    if ($count === 0) {
                        $themes_path      = explode('usr/themes/', $build_js_name);
                        $real_src         = '/usr/themes/' . $themes_path[1];
                        $value->plaintext = html_entity_decode($value->innerhtml . "<script src=\"{$real_src}\"></script>");
                    } else {
                        $value->plaintext = '';
                    }
                    $count++;
                }
            }
        }

        if (!$build_js_is_exist) {
            file_put_contents($build_js_name, $build_js);
        }
        return $htmlDomParser->save();
    }

    private function buildCss($build_css_name, $html)
    {
        $build_css_is_exist = file_exists($build_css_name);
        $htmlDomParser      = HtmlDomParser::str_get_html($html);
        $element            = $htmlDomParser->getElementsByTagName("link");
        $build_css          = '';
        $count              = 0;
        foreach ($element as $value) {
            $ignore_assets = Config::get('build.ignore_assets');
            $href          = $value->getAttribute('href');
            if (mb_strpos($href, '.css')) {
                if (!$build_css_is_exist) {
                    switch (true) {
                        case strpos($href, "//") !== false:
                            $href_path = $href;
                            break;
                        case strpos($href, '{{$this->options->themeUrl(\'') !== false:
                            $href_path = THEMES_PATH . '/' . trim(str_replace(['{{$this->options->themeUrl(\'', '\')}}'], ['', ''], $href));
                            $href_path = explode('.css', $href_path)[0] . ".css";
                            break;
                        case strpos($href, '{{$this->options->themeUrl("') !== false:
                            $href_path = THEMES_PATH . '/' . trim(str_replace(['{{$this->options->themeUrl("', '")}}'], ['', ''], $href));
                            $href_path = explode('.css', $href_path)[0] . ".css";
                            break;
                        default:
                            throw new \RuntimeException("build css error {$href}");
                    }
                    $cacheKey = "build:css:" . md5($href);
                    $temp_css = Cache::get($cacheKey);
                    if (!$temp_css && !in_array($href_path, $ignore_assets)) {
                        $temp_css = file_get_contents($href_path);
                        Cache::set($cacheKey, $temp_css);
                    }
                    $build_css .= "\r\n/* {$href_path} */\r\n";
                    $build_css .= $temp_css;
                    $build_css .= "\r\n";
                }
                if (!in_array($href_path, $ignore_assets)) {
                    if ($count === 0) {
                        $themes_path      = explode('usr/themes/', $build_css_name);
                        $real_href        = '/usr/themes/' . $themes_path[1];
                        $value->plaintext = html_entity_decode($value->innerhtml . "<link rel=\"stylesheet\" href=\"{$real_href}\">");
                    } else {
                        $value->plaintext = '';
                    }
                    $count++;
                }
            }
        }

        if (!$build_css_is_exist) {
            file_put_contents($build_css_name, $build_css);
        }

        return $htmlDomParser->save();
    }

}
